package com.xbongbong.saas.model.impl;

import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.PayErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.PaymentBalanceInsertConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.dao.PayBalanceDao;
import com.xbongbong.saas.domain.entity.PayBalanceEntity;
import com.xbongbong.saas.enums.PayBalanceEnum;
import com.xbongbong.saas.model.PayBalanceModel;
import org.elasticsearch.action.support.WriteRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author 徐俊杰
 * @date 2020/2/24 15:36
 * @since v1.0
 */
@Service("payBalanceModel")
public class PayBalanceModelImpl implements PayBalanceModel {
    @Resource
    private PayBalanceDao payBalanceDao;
    @Resource
    private PaasEsModel paasEsModel;
    public static final Logger LOG = LoggerFactory.getLogger(PayBalanceModelImpl.class);

    @Override
    public PayBalanceEntity getBySupplierId(Long supplierId, String corpid) {
        return payBalanceDao.getBySupplierId(supplierId,corpid);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer insert(PayBalanceEntity entity) throws XbbException {
        Double advancePayBalance = entity.getAdvancePayBalance();
        if (advancePayBalance == null || Objects.equals(BasicConstant.ZERO_DOUBLE, advancePayBalance)) {
            throw new XbbException(PayErrorCodeEnum.API_ERROR_226014);
        }
        long now = DateTimeUtil.getInt();
        entity.setAddTime(now);
        entity.setUpdateTime(now);
        Integer insert;
        try {
            payBalanceDao.insert(entity);
            insert = PaymentBalanceInsertConstant.INSERT;
        } catch (Exception e) {
            String str = "Duplicate entry";
            String str1 = "for key 'idx_corpid_supplier'";
            String message = e.getCause().getMessage();
            //如果是唯一键重复，则进行更新处理
            if(message.contains(str) && message.contains(str1)){
                update(entity);
                insert = PaymentBalanceInsertConstant.UPDATE;
            }else{
                throw  e;
            }
        }
        entity = getBySupplierId(entity.getSupplierId(),entity.getCorpid());
        if(entity.getAdvancePayBalance() < 0 ){
            throw  new XbbException(PayErrorCodeEnum.API_ERROR_226015);
        }
        InsertDTO insertDTO = getSaveDTO(entity,IndexTypeEnum.IDX_PAY_BALANCE);
        paasEsModel.insert(insertDTO);
        return insert;
    }

    @Override
    public Integer update(PayBalanceEntity entity) throws XbbException {
        return null;
    }

    @Override
    public PayBalanceEntity getById(Long id, String corpid) {
        return payBalanceDao.getByKey(id,corpid);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer update(PayBalanceEntity entity,boolean updateDel) throws XbbException {
        Double advancePayBalance = entity.getAdvancePayBalance();
        if (advancePayBalance == null || Objects.equals(BasicConstant.ZERO_DOUBLE, advancePayBalance)) {
            throw new XbbException(PayErrorCodeEnum.API_ERROR_226014);
        }
        Integer balance;
        Long id = entity.getId();
        if (id == null || id == 0L) {
            balance = payBalanceDao.updatePayBalanceByCorpidAndSupplierId(advancePayBalance, entity.getCorpid(), entity.getSupplierId());
        }else{
            if(updateDel){
                balance = payBalanceDao.updatePayBalanceDelByCorpidAndId(advancePayBalance,entity.getCorpid(),entity.getId());
            }else {
                balance = payBalanceDao.updatePayBalanceByCorpidAndId(advancePayBalance,entity.getCorpid(),entity.getId());
            }
        }
        entity = getBySupplierId(entity.getSupplierId(),entity.getCorpid());
        if(entity.getAdvancePayBalance() < 0 ){
            throw  new XbbException(PayErrorCodeEnum.API_ERROR_226015);
        }
        InsertDTO insertDTO = getSaveDTO(entity,IndexTypeEnum.IDX_PAY_BALANCE);
        paasEsModel.update(insertDTO);
        return balance;
    }

    @Override
    public List<PayBalanceEntity> findEntitys(Map<String, Object> param) {
        return payBalanceDao.findEntitys(param);
    }

    @Override
    public Integer getEntitysCount(Map<String, Object> param) {
        return payBalanceDao.getEntitysCount(param);
    }

    @Override
    public List findEntitysWithoutSub(Map<String, Object> param) {
        return null;
    }

    @Override
    public InsertDTO getSaveDTO(PayBalanceEntity PayBalanceEntity, IndexTypeEnum indexTypeEnum) throws XbbException {
        InsertDTO insertDTO = new InsertDTO();
        //customerId也可以做主键
        insertDTO.setEsId(PayBalanceEntity.getCorpid() + "_" + PayBalanceEntity.getId());
        insertDTO.setSource(BeanUtil.convertBean2Map(PayBalanceEntity, false, true));
        insertDTO.setIndexTypeEnum(indexTypeEnum);
        return insertDTO;
    }

    @Override
    public List<PayBalanceEntity> getBySupplierIds(Collection<Long> supplierIds, String corpid) {
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("supplierIds", supplierIds);
        param.put("corpid", corpid);
        param.put("del", 0);
        return findEntitys(param);
    }

    private List<PayBalanceEntity> getBySupplierIds(List<Long> supplierIds, String corpid,String columns) {
        return payBalanceDao.getBySupplierIds(supplierIds,corpid,columns);
    }

    @Override
    @Transactional(rollbackFor = XbbException.class)
    public Integer updateBatchByCorpidAndSupplierId(List<PayBalanceEntity> list, String corpid) throws XbbException {
        if (list.size() == 0) {
            return BasicConstant.ZERO;
        }
        Integer integer;
        try {
            integer = payBalanceDao.updateBatchByCorpidAndSupplierId(list, corpid);
            List<Long> supplierIds = new ArrayList<>(list.size());
            for (PayBalanceEntity PayBalanceEntity : list) {
                supplierIds.add(PayBalanceEntity.getSupplierId());
            }
            list = getBySupplierIds(supplierIds,corpid,"id,corpid,advance_pay_balance,update_time");
            List<InsertDTO> insertList = new ArrayList<>();
            for (PayBalanceEntity PayBalanceEntity : list) {
                if(PayBalanceEntity.getAdvancePayBalance() < 0 ){
                    throw  new XbbException(PayErrorCodeEnum.API_ERROR_226015);
                }
                InsertDTO insertDTO = new InsertDTO();
                insertDTO.setEsId(corpid + "_" + PayBalanceEntity.getId());
                Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                map.put(PayBalanceEnum.ADVANCE_PAY_BALANCE.getAttr(),PayBalanceEntity.getAdvancePayBalance());
                map.put(PayBalanceEnum.UPDATE_TIME.getAttr(),PayBalanceEntity.getUpdateTime());
                insertDTO.setSource(map);
                insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAY_BALANCE);
                insertList.add(insertDTO);
            }
            //保证更新ES是最后一行，如果不能要在catch写ES的回滚
            paasEsModel.updateBatch(insertList);
        } catch (Exception e) {
            LOG.error(PayErrorCodeEnum.API_ERROR_226016.getMsg(),e);
            throw e;
        }
        return integer;
    }

    @Override
    public Integer deleteBatch(List<Long> idIn, String corpid) throws XbbException {
        Integer delete = 0;
        if(CollectionsUtil.isEmpty(idIn)){
            return delete;
        }
        delete = payBalanceDao.deleteBatch(idIn, corpid);
        updateDel(idIn, corpid,DelEnum.DELETE.getDel());
        return delete;
    }

    @Override
    public Integer deleteBatchRollback(List<Long> idIn, String corpid) throws XbbException {
        Integer delete = 0;
        if(CollectionsUtil.isEmpty(idIn)){
            return delete;
        }
        //回滚ES，不需要修改数据库，数据库已经回滚
        updateDel(idIn, corpid,DelEnum.NORMAL.getDel());
        return 1;
    }

    private void updateDel(List<Long> idIn, String corpid,Integer del) throws XbbException {
        List<InsertDTO> insertList = new ArrayList<>();
        for (Long aLong : idIn) {
            InsertDTO insertDTO = new InsertDTO();
            insertDTO.setEsId(corpid + "_" + aLong);
            Map<String, Object> map = new HashMap<>(2);
            map.put(StringConstant.DEL, del);
            map.put(PayBalanceEnum.UPDATE_TIME.getAttr(), DateUtil.getNow());
            insertDTO.setSource(map);
            insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAY_BALANCE);
            insertList.add(insertDTO);
        }
        //保证更新ES是最后一行，如果不能要在catch写ES的回滚
        paasEsModel.updateBatch(insertList);
    }

    @Override
    public void updateBatchAdvance(String corpid, List<PayBalanceEntity> list) throws XbbException {
        payBalanceDao.updateBatchAdvanceByCorpidAndSupplierId(list, corpid);
        //处理es
        List<InsertDTO> insertList = new ArrayList<>();
        for (PayBalanceEntity balanceEntity : list) {
            Map<String,Object> map = new HashMap<>();
            map.put("advancePayBalance", balanceEntity.getAdvancePayBalance());
            InsertDTO insertDTO = new InsertDTO();
            insertDTO.setEsId(corpid + "_" + balanceEntity.getId());
            insertDTO.setSource(map);
            insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_PAY_BALANCE);
            insertList.add(insertDTO);
        }
        //保证更新ES是最后一行，如果不能要在catch写ES的回滚
        paasEsModel.updateBatch(insertList);
    }

    @Override
    public Integer updateTime(Long id,String corpid) throws XbbException {
        long now = DateUtil.getInt();
        // 更新时间
        Integer success = payBalanceDao.updateTime(now, id, corpid);
        // 更新es
        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
        paasFormDataEntity.setId(id);
        paasFormDataEntity.setDataId(id);
        paasFormDataEntity.setCorpid(corpid);
        paasFormDataEntity.setUpdateTime(now);
        InsertDTO insertDTO = paasEsModel.getSaveDTO(paasFormDataEntity, IndexTypeEnum.IDX_PAY_BALANCE);
        paasEsModel.update(insertDTO);
        return success;
    }


    @Override
    public Integer updateBatch(List<UpdateDataEntity> list, String corpid) throws XbbException {
        Integer integer = 0;
        if (CollectionsUtil.isNotEmpty(list)) {
            integer = payBalanceDao.updateBatch(list, corpid);
            paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_PAY_BALANCE);
        }
        return integer;
    }

    @Override
    public Integer updateBatch(List<UpdateDataEntity> list, String corpid, WriteRequest.RefreshPolicy refreshPolicy) throws XbbException {
        Integer integer = 0;
        if (CollectionsUtil.isEmpty(list)) {
           return integer;
        }
        integer = payBalanceDao.updateBatch(list, corpid);
        paasEsModel.updateBatchMuchField(list, IndexTypeEnum.IDX_PAY_BALANCE, refreshPolicy);
        return integer;
    }
}
